use num_enum::{IntoPrimitive, TryFromPrimitive};
use tokio::sync::mpsc;
use crate::configs::AgentConf;
use tokio::sync::mpsc::{Receiver, Sender};
use crate::cloud_pkt::CloudPacket;
use crate::error::Error;

///
/// Cache类型
///
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
#[repr(u8)]
pub enum CacheType {
    Realtime = 0x01,
    Retry = 0x02,
    Reissue = 0x03,
}


pub struct MsgCache {
    pub msg_rt_tx: Sender<CloudPacket>,
    pub msg_rt_rx: Receiver<CloudPacket>,
    pub msg_retry_tx: Sender<CloudPacket>,
    pub msg_retry_rx: Receiver<CloudPacket>,
    pub msg_reissue_tx: Sender<CloudPacket>,
    pub msg_reissue_rx: Receiver<CloudPacket>,
}

impl MsgCache {
    pub fn build(agent_conf: &AgentConf) -> Self {
        let (cache_msg_rt_tx, cache_msg_rt_rx) = mpsc::channel::<CloudPacket>(agent_conf.cache_size_rt as usize);
        let (cache_msg_retry_tx, cache_msg_retry_rx) = mpsc::channel::<CloudPacket>(agent_conf.cache_size_retry as usize);
        let (cache_msg_reissue_tx, cache_msg_reissue_rx) = mpsc::channel::<CloudPacket>(agent_conf.cache_size_reissue as usize);
        Self {
            msg_rt_tx: cache_msg_rt_tx,
            msg_rt_rx: cache_msg_rt_rx,
            msg_retry_tx: cache_msg_retry_tx,
            msg_retry_rx: cache_msg_retry_rx,
            msg_reissue_tx: cache_msg_reissue_tx,
            msg_reissue_rx: cache_msg_reissue_rx,
        }
    }

    pub async fn write_pkt(&mut self, cache_type: CacheType, pkt: CloudPacket) -> Result<(), Error> {
        match cache_type {
            CacheType::Realtime => {
                let ret = self.msg_rt_tx.send(pkt.clone()).await;
                if ret.is_err() {
                    return Err(Error::SenderError(ret.unwrap_err().to_string()));
                }
            }
            CacheType::Retry => {
                let ret = self.msg_retry_tx.send(pkt.clone()).await;
                if ret.is_err() {
                    return Err(Error::SenderError(ret.unwrap_err().to_string()));
                }
            }
            CacheType::Reissue => {
                let ret = self.msg_reissue_tx.send(pkt.clone()).await;
                if ret.is_err() {
                    return Err(Error::SenderError(ret.unwrap_err().to_string()));
                }
            }
        }
        Ok(())
    }
    // pub async fn try_read_pkt(&mut self, cache_type: CacheType) {
    //     match cache_type {
    //         CacheType::Realtime => {
    //             return self.msg_rt_rx.recv();
    //         }
    //         CacheType::Retry => {
    //             return self.msg_retry_rx.recv();
    //         }
    //         CacheType::Reissue => {
    //             return self.msg_reissue_rx.recv();
    //         }
    //     }
    // }
}